<template>
  <div class="upload-container">
    <div class="toolbar">
      <el-button type="primary" @click="showConfigDialog">
        <el-icon><setting /></el-icon>
        上传文件并配置
      </el-button>
    </div>

    <el-dialog
        v-model="configDialogVisible"
        title="上传文件并配置"
        width="600px" :close-on-click-modal="false"
        @closed="resetForm" >
      <el-upload
          class="upload-in-dialog"
          drag
          multiple
          :action="uploadUrl"
          :headers="headers"
          :data="formData"
          :limit="maxFiles"
          :on-exceed="handleExceed"
          :before-upload="beforeUpload"
          :on-success="handleSuccess"
          :on-error="handleError"
          :on-progress="handleProgress"
          :file-list="fileList"
          :accept="allowedFileTypes.join(',')"
          :show-file-list="true"
          :auto-upload="false" ref="uploadRef" @remove="handleRemove" >
        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
        <div class="el-upload__text">
          将文件拖到此处或<em>点击选择文件</em> </div>
        <template #tip>
          <div class="el-upload__tip">
            支持 {{ allowedExtensions.join(', ') }} 格式文件，单个文件不超过 {{ maxFileSizeMB }}MB
          </div>
        </template>
      </el-upload>

      <el-form
          ref="configForm"
          :model="fileConfig"
          label-width="100px"
          :rules="formRules"
          style="margin-top: 20px;" >
        <el-form-item label="文件类型：" prop="fileType">
          <el-select
              v-model="fileConfig.fileType"
              placeholder="请选择文件类型"
              class="full-width"
          >
            <el-option
                v-for="type in fileTypes"
                :key="type.value"
                :label="type.label"
                :value="type.value"
            />
          </el-select>
        </el-form-item>

        <el-form-item label="文件分类：" prop="category">
          <el-select
              v-model="fileConfig.category"
              placeholder="请选择分类"
              class="full-width"
          >
            <el-option
                v-for="cate in categories"
                :key="cate.value"
                :label="cate.label"
                :value="cate.value"
            />
          </el-select>
        </el-form-item>

        <el-form-item label="可见范围：" prop="visibility">
          <el-radio-group v-model="fileConfig.visibility">
            <el-radio label="public">公开</el-radio>
            <el-radio label="internal">内部</el-radio>
            <el-radio label="private">私有</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item label="文件描述：" prop="description">
          <el-input
              v-model="fileConfig.description"
              type="textarea"
              :rows="3"
              placeholder="请输入文件描述（200字以内）"
              maxlength="200"
              show-word-limit
          />
        </el-form-item>
      </el-form>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="configDialogVisible = false">取消</el-button>
          <el-button
              type="primary"
              :loading="uploading"
              @click="handleUploadWithConfig"
              :disabled="fileList.length === 0 || uploading" > {{ uploading ? '上传中...' : '开始上传' }}
          </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import {ref, reactive, computed, nextTick} from 'vue'; // 导入 nextTick
import axios from 'axios';
import {
  ElMessage,
  ElMessageBox,
  ElUpload,
  ElDialog,
  ElForm,
  ElFormItem,
  ElSelect,
  ElOption,
  ElRadioGroup,
  ElRadio,
  ElInput
} from 'element-plus';
import {Setting, UploadFilled} from '@element-plus/icons-vue';

const props = defineProps({
  uploadUrl: {
    type: String,
    required: true
  },
  maxFileSizeMB: {
    type: Number,
    default: 5
  },
  allowedFileTypes: {
    type: Array,
    default: () => ['image/*', 'application/pdf', 'text/plain']
  },
  maxFiles: {
    type: Number,
    default: 10
  },
  headers: {
    type: Object,
    default: () => ({})
  },
  formData: {
    type: Object,
    default: () => ({}) // 这里的 formData 可以在 showConfigDialog 之前用于一些固定参数
  }
});

const emit = defineEmits(['upload-success', 'upload-error']);

// 响应式状态
const fileList = ref([]); // 用于显示在 el-upload 中的文件列表
const configDialogVisible = ref(false);
const uploading = ref(false);
const configForm = ref(null);
const uploadRef = ref(null); // el-upload 组件的引用

// 文件配置表单
const fileConfig = reactive({
  fileType: '',
  category: '',
  visibility: 'internal',
  description: ''
});

// 表单验证规则
const formRules = {
  fileType: [{required: true, message: '请选择文件类型', trigger: 'change'}],
  category: [{required: true, message: '请选择文件分类', trigger: 'change'}],
  visibility: [{required: true, message: '请选择可见范围', trigger: 'change'}]
};

// 可选项配置
const fileTypes = [
  {value: 'document', label: '文档'},
  {value: 'image', label: '图片'},
  {value: 'video', label: '视频'},
  {value: 'other', label: '其他'}
];

const categories = [
  {value: 'finance', label: '财务文件'},
  {value: 'project', label: '项目文档'},
  {value: 'hr', label: '人事档案'}
];

// 计算属性
const allowedExtensions = computed(() => {
  const exts = [];
  props.allowedFileTypes.forEach(type => {
    const match = type.match(/\/(\w+)$/);
    if (match) {
      exts.push(match[1].toUpperCase());
    } else if (type.includes('/')) { // Handle specific types like application/pdf
      const parts = type.split('/');
      if (parts.length > 1) {
        exts.push(parts[1].toUpperCase());
      }
    } else { // Handle types like .docx, .xlsx etc. if needed
      exts.push(type.replace('.', '').toUpperCase());
    }
  });
  // Add common document extensions if 'document' type is allowed
  if (props.allowedFileTypes.includes('application/pdf')) {
    if (!exts.includes('PDF')) exts.push('PDF');
  }
  if (props.allowedFileTypes.includes('text/plain')) {
    if (!exts.includes('PLAIN')) exts.push('TXT'); // Use TXT for plain text
  }
  // Add more specific extensions based on common usage if image/* or video/* are allowed
  if (props.allowedFileTypes.includes('image/*')) {
    ['JPG', 'JPEG', 'PNG', 'GIF', 'BMP'].forEach(ext => {
      if (!exts.includes(ext)) exts.push(ext);
    });
  }
  if (props.allowedFileTypes.includes('video/*')) {
    ['MP4', 'AVI', 'MOV', 'WMV'].forEach(ext => {
      if (!exts.includes(ext)) exts.push(ext);
    });
  }


  return [...new Set(exts)]; // Remove duplicates
});


// 方法定义
const showConfigDialog = () => {
  // 打开对话框
  configDialogVisible.value = true;
  // 重置表单和文件列表，确保每次打开都是新的状态
  resetForm();
};

// before-upload 钩子，在文件上传前触发 (这里是文件被添加到列表前触发)
const beforeUpload = (file) => {
  const isTypeValid = props.allowedFileTypes.some(type => {
    if (type.endsWith('/*')) {
      return file.type.startsWith(type.split('/')[0]);
    }
    return file.type === type;
  });

  const isSizeValid = file.size <= props.maxFileSizeMB * 1024 * 1024;

  if (!isTypeValid) {
    ElMessage.error(`不支持的文件类型: ${file.type}`);
    return false; // 阻止文件添加到列表
  }

  if (!isSizeValid) {
    ElMessage.error(`文件大小不能超过 ${props.maxFileSizeMB}MB`);
    return false; // 阻止文件添加到列表
  }

  // 文件校验通过，手动将文件添加到 el-upload 组件内部的文件列表
  // 使用 nextTick 确保在 DOM 更新后执行
  nextTick(() => {
    if (uploadRef.value) {
      // 这是一个非公共方法，但常用于手动控制文件添加
      // 注意：Element Plus 版本更新可能导致此方法名称变化或行为改变
      uploadRef.value.handleStart(file);
      console.log('File added to el-upload internal list:', file); // 添加控制台日志
    }
  });


  console.log('File passed validation in beforeUpload:', file); // 添加控制台日志

  return false; // 阻止 el-upload 的默认上传行为
};

const handleUploadWithConfig = async () => {
  try {
    // 验证配置表单
    const valid = await configForm.value.validate();
    if (!valid) return;

    // 检查是否有文件需要上传
    // 现在 fileList 应该是由 el-upload 内部同步更新的
    if (fileList.value.length === 0) {
      ElMessage.warning('没有文件需要上传');
      // 理论上开始上传按钮在没有文件时是禁用的，这里是双重检查
      return;
    }

    uploading.value = true;

    const formData = new FormData();
    // 将配置数据添加到 formData
    formData.append('config', JSON.stringify({
      ...fileConfig,
      uploadTime: new Date().toISOString()
    }));

    // 将文件添加到 formData
    // 遍历 fileList，获取原始文件对象
    fileList.value.forEach((fileItem) => {
      // 更新文件状态为 uploading
      // 注意：直接修改 fileList.value 中的对象属性可能需要确保其响应性
      // Element Plus 文件对象通常是响应式的
      fileItem.status = 'uploading';
      // 确保文件字段名与后端接口要求一致，这里使用 'files' 或 'file'
      formData.append(`files`, fileItem.raw); // 使用 fileItem.raw 获取原始文件
    });


    // 发送上传请求
    const response = await axios.post(props.uploadUrl, formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
        ...props.headers
      },
      // 监听上传进度
      onUploadProgress: (progressEvent) => {
        const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
        // 更新文件列表中的进度条
        fileList.value.forEach(fileItem => {
          // Element Plus 文件对象有 percentage 属性
          if (fileItem.status === 'uploading' && fileItem.percentage !== undefined) {
            fileItem.percentage = percentCompleted;
          }
        });
        console.log(`Upload progress: ${percentCompleted}%`);
      }
    });

    // 上传成功，更新文件状态为 success
    fileList.value.forEach(fileItem => {
      if (fileItem.status === 'uploading') {
        fileItem.status = 'success';
        // 如果后端返回了文件信息（如 URL），可以在这里更新 fileItem
        // fileItem.url = response.data.fileUrls[fileItem.name]; // 示例
      }
    });

    ElMessage.success('文件上传成功');
    emit('upload-success', response.data);
    // 上传成功后不清空文件列表，让用户看到上传结果
    // configDialogVisible.value = false; // 不在这里关闭，让用户看到结果

  } catch (error) {
    // 上传失败，更新文件状态为 fail
    fileList.value.forEach(fileItem => {
      if (fileItem.status === 'uploading') {
        fileItem.status = 'fail';
      }
    });
    ElMessage.error(`上传失败: ${error.message || '未知错误'}`);
    emit('upload-error', error);
  } finally {
    uploading.value = false;
    // configDialogVisible.value = false; // 不在这里关闭
  }
};

// 重置表单和文件列表
const resetForm = () => {
  if (configForm.value) {
    configForm.value.resetFields();
  }
  // 清空文件列表
  // fileList.value = []; // 不再直接操作 fileList.value
  // 清空 el-upload 组件内部的文件列表状态，这会自动更新 fileList.value
  if (uploadRef.value) {
    uploadRef.value.clearFiles();
  }
};


// el-upload 内部的成功、失败、进度处理（当 auto-upload="false" 时，这些不会被 el-upload 自身触发）
// 这些方法签名保留，但实际上传逻辑已在 handleUploadWithConfig 中实现
const handleSuccess = (response, uploadFile, uploadFiles) => {
  console.log('el-upload handleSuccess (not typically used with manual axios upload):', response, uploadFile, uploadFiles);
};

const handleError = (error, uploadFile, uploadFiles) => {
  console.error('el-upload handleError (not typically used with manual axios upload):', error, uploadFile, uploadFiles);
};

const handleProgress = (event, uploadFile, uploadFiles) => {
  console.log('el-upload handleProgress (not typically used with manual axios upload):', event, uploadFile, uploadFiles);
};


const handleExceed = () => {
  ElMessage.warning(`最多只能上传 ${props.maxFiles} 个文件`);
};

// 当文件列表中的文件被移除时触发
const handleRemove = (uploadFile) => {
  console.log('File removed:', uploadFile);
  // 当 el-upload 的 clearFiles 或用户点击移除按钮时，这个方法会被触发
  // fileList.value 会自动更新，无需手动 splice
  // 如果需要额外的逻辑，可以在这里添加
};

</script>

<style scoped>
.upload-container {
  padding: 20px;
  background: #ffffff;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
  /* 移除主容器的拖拽样式，因为拖拽区域移到对话框里了 */
}

.toolbar {
  margin-bottom: 20px;
  text-align: center; /* 让按钮居中 */
}

/* 移除 .upload-main 的样式，因为它不再用于布局 */


.upload-in-dialog :deep(.el-upload-dragger) {
  width: 100%; /* 让对话框内的拖拽区域宽度自适应 */
}

.full-width {
  width: 100%;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

:deep(.el-dialog__body) {
  padding: 20px 25px;
  /* 调整对话框 body 的内边距 */
}

.el-upload__tip {
  margin-top: 10px;
  color: #909399;
  font-size: 12px;
}
</style>
